// Copyright (C) 2022 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dao

import (
  "context"
  "database/sql"
  dbutil "dist/db"
  "dist/model"
  "dist/utils"
  "errors"
  "fmt"
  "time"
)

func QueryUserByUid(uid string) (model.User, error) {
  var user model.User
  conn, err := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  err = conn.QueryRowContext(ctx, "SELECT user_id,uid,create_time FROM sp_user where uid=$1", uid).Scan(&user.UserId, &user.Uid, &user.CreateTime)
  defer conn.Close()
  if err != nil {
    utils.Error.Printf("uid is %s, err is %v", uid, err)
    return user, err
  }
  if err == sql.ErrNoRows {
    utils.Error.Printf("%s", "no such user")
    return user, errors.New("no such user")
  }
  return user, nil
}

func InsertUser(user model.User) int64 {
  conn, _ := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  var userId int64
  result := conn.QueryRowContext(ctx, "INSERT INTO sp_user(uid,create_time) VALUES($1,$2) RETURNING user_id", user.Uid, user.CreateTime).Scan(&userId)
  defer conn.Close()
  if result != nil {
    return -1
  }
  return userId
}

func InsertUserAccess(accessRecord model.AccessRecord) (bool, int64) {
  conn, _ := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  var accessId int64
  result := conn.QueryRowContext(ctx, "INSERT INTO sp_user_access(user_id,access_time) VALUES($1,$2) RETURNING access_id", accessRecord.UserId, accessRecord.AccessTime).Scan(&accessId)
  defer conn.Close()
  if result != nil {
    return false, 0
  }
  return true, accessId
}

func QueryHomePageVisit() []interface{} {
  conn, err := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  rows, err := conn.QueryContext(ctx, utils.PAGE_VISIT)
  defer rows.Close()
  defer conn.Close()
  if err != nil {
    utils.Error.Printf("sqlStr is %s, error is %v", utils.PAGE_VISIT, err)
    return nil
  }
  var charts []interface{}
  for rows.Next() {
    var char model.HomePageChar
    _ = rows.Scan(&char.Key, &char.Value, &char.Index)
    charts = append(charts, char)
  }
  return charts
}

func QueryHomePageUser() []interface{} {
  conn, err := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  rows, err := conn.QueryContext(ctx, utils.PAGE_USER)
  defer rows.Close()
  defer conn.Close()

  if err != nil {
    utils.Error.Printf("sqlStr is %s, error is %v", utils.PAGE_USER, err)
    return nil
  }
  var charts []interface{}
  for rows.Next() {
    var char model.HomePageChar
    _ = rows.Scan(&char.Key, &char.Value, &char.Index)
    charts = append(charts, char)
  }
  return charts
}

func QueryUserRecentAccessRecords(id int64, visitId int64) (model.AccessRecord, error) {
  var userAccess model.AccessRecord
  conn, err := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  err = conn.QueryRowContext(ctx, "SELECT user_id,access_time,effective FROM sp_user_access where user_id=$1 AND access_id=$2 ORDER BY access_time desc limit 1 ", id, visitId).Scan(&userAccess.UserId, &userAccess.AccessTime, &userAccess.Effective)
  defer conn.Close()
  if err != nil {
    return userAccess, err
  }
  if err == sql.ErrNoRows {
    return userAccess, errors.New("no such user")
  }
  return userAccess, nil
}

func UpdateAccessRecord(id int64, accessTime time.Time, effectiveCount int32, accessId int64) bool {
  conn, _ := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  _, err := conn.ExecContext(ctx, "update sp_user_access set effective=$1 where user_id=$2 and access_time=$3 and access_id=$4", effectiveCount, id, accessTime, accessId)
  defer conn.Close()
  if err != nil {
    return false
  }
  return true
}

func QueryHomePageChar(startTime time.Time, endTime time.Time, interval string) map[string][]model.HomePageChar {
  conn, err := dbutil.GetConnection()
  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()
  fsqlStr := fmt.Sprintf(utils.HOME_PAGE_CHART_SQL, interval, interval, interval, interval)
  rows, err := conn.QueryContext(ctx, fsqlStr, startTime, endTime)
  defer rows.Close()
  defer conn.Close()
  if err != nil {
    utils.Error.Printf("sqlStr is %s, error is %v", fsqlStr, err)
    return nil
  }
  colletChar := make(map[string][]model.HomePageChar)
  var addUserCharts []model.HomePageChar
  var activeUserCharts []model.HomePageChar
  var accessCharts []model.HomePageChar
  var totalUserCharts []model.HomePageChar
  beforeTotalUser := 0
  firstFlag := true
  for rows.Next() {
    var char model.HomePageChar
    _ = rows.Scan(&char.Key, &char.Date, &char.Value, &char.UserId)
    if char.Key == "beforeTotalUser" {
      beforeTotalUser = char.Value
    }
    if char.Key == "addUser" {
      addUserCharts = append(addUserCharts, char)
    }
    if char.Key == "activeUser" {
      activeUserCharts = append(activeUserCharts, char)
    }
    if char.Key == "access" {
      accessCharts = append(accessCharts, char)
    }
    if char.Key == "totalUser" {
      if firstFlag {
        char.Value += beforeTotalUser
      }
      firstFlag = false
      totalUserCharts = append(totalUserCharts, char)
    }
  }
  //未查询到totalUser
  if(firstFlag){
    var char model.HomePageChar
    char.Key = "totalUser"
    char.Date = startTime.String()
    char.Value = beforeTotalUser
    totalUserCharts = append(totalUserCharts, char)
  }
  colletChar["addUSer"] = addUserCharts
  colletChar["activeUser"] = activeUserCharts
  colletChar["access"] = accessCharts
  colletChar["totalUser"] = totalUserCharts
  return colletChar
}
